home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume5 / fsanalyze4.1 / part03 < prev    next >
Encoding:
Internet Message Format  |  1989-02-03  |  30.6 KB

  1. Path: xanth!nic.MR.NET!hal!ncoast!allbery
  2. From: mjy@sdti.sdti.com (Michael J. Young)
  3. Newsgroups: comp.sources.misc
  4. Subject: v05i070: Fsanalyze Version 4.1, Part 3/3
  5. Message-ID: <340@sdti.SDTI.COM>
  6. Date: 7 Dec 88 00:11:37 GMT
  7. Sender: allbery@ncoast.UUCP
  8. Reply-To: mjy@sdti.sdti.com (Michael J. Young)
  9. Organization: Software Development Technologies, Sudbury MA
  10. Lines: 816
  11. Approved: allbery@ncoast.UUCP
  12.  
  13. Posting-number: Volume 5, Issue 70
  14. Submitted-by: "Michael J. Young" <mjy@sdti.sdti.com>
  15. Archive-name: fsanalyze4.1/[art03
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of archive 3 (of 3)."
  24. # Contents:  chkfile.c fsconfig.h
  25. # Wrapped by mjy@sdti on Wed Nov 30 15:54:17 1988
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f chkfile.c -a "${1}" != "-c" ; then 
  28.   echo shar: Will not over-write existing file \"chkfile.c\"
  29. else
  30. echo shar: Extracting \"chkfile.c\" \(15316 characters\)
  31. sed "s/^X//" >chkfile.c <<'END_OF_chkfile.c'
  32. Xstatic char sccsid[] = "@(#)$Id: chkfile.c, V4.1 88/11/16 17:29:30 $";
  33. X
  34. X/*
  35. X * chkfile.c - analyze file
  36. X * Version  : 4.1 - 88/11/16 17:29:30
  37. X *
  38. X * Author   : Michael J. Young
  39. X * USmail   : Software Development Technologies, Inc.
  40. X *            375 Dutton Rd
  41. X *            Sudbury MA 01776
  42. X * UUCP     : harvard!sdti!mjy
  43. X * Internet : mjy@sdti.SDTI.COM
  44. X *
  45. X * =========================================================================
  46. X * Note : This program has been placed in the public domain to permit
  47. X * unrestricted distribution and use.  I have placed no copyright on it, but
  48. X * I request that you keep me informed about any enhancements and bug fixes
  49. X * you make so I can keep an up-to-date copy for further distribution.
  50. X *
  51. X * This program is being provided "as is", with no warrantee as to safety or
  52. X * accuracy of results.  Use at your own risk.
  53. X * =========================================================================
  54. X */
  55. X
  56. X/*
  57. X * Modification History:
  58. X *
  59. X * Thu Jul 28 15:00:44 EDT 1988 - M. Young (mjy@sdti.SDTI.COM),
  60. X *    Extracted from fsanalyze.c
  61. X *
  62. X * Mon Aug 08 11:27:39 EDT 1988 - M. Young (mjy@sdti.SDTI.COM),
  63. X *    Revised OS_TYPE and FS_TYPE macros to avoid name-space conflicts
  64. X *
  65. X * Fri Nov 11 16:25:44 EST 1988 - M. Young (mjy@sdti.SDTI.COM),
  66. X *    Fixed boundary condition error in scan().
  67. X *
  68. X * Wed Nov 16 11:31:32 EST 1988 - M. Young (mjy@sdti.SDTI.COM),
  69. X *    Placed under SCCS
  70. X */
  71. X
  72. X#include "fsconfig.h"
  73. X#include "fsanalyze.h"
  74. X
  75. X/*
  76. X * chk_indirects : scans a block containing data block numbers, looking
  77. X * for block numbers that are not sequential.
  78. X */
  79. Xdaddr_t chk_indirects (block, cur_pos, data, inode, lbn)
  80. Xdaddr_t block;                    /* indirect block to check */
  81. Xdaddr_t cur_pos;                  /* current block offset */
  82. Xstruct file_data *data;           /* current file statistics */
  83. Xstruct dinode *inode;             /* inode being processed */
  84. Xdaddr_t lbn;                      /* logical blk_no of 1st data block */
  85. X{
  86. X    daddr_t ind_blk[MAXINDIR];    /* holds an indirect block */
  87. X    int num_blocks;               /* number of data blocks in
  88. X                                   * an indirect block */
  89. X    daddr_t pos;                  /* current data block */
  90. X    daddr_t new_pos;              /* next data block */
  91. X    int i;                        /* loop counter */
  92. X    boolean sparse;               /* potential sparse 
  93. X                                   * file detected */
  94. X
  95. X    num_blocks = nindir(fil_sys);
  96. X    data->total_blocks += (bsize(fil_sys) / fsize(fil_sys));
  97. X
  98. X    /*
  99. X     * the indirect block itself should be in the correct sequence
  100. X     * with the data blocks
  101. X     */
  102. X    test_fragmentation (block, cur_pos, data);
  103. X
  104. X    /*
  105. X     * get the indirect block
  106. X     */
  107. X    if (fseek (fsys, block * block_size, 0)){
  108. X        error (errno, "\nerror seeking indirect block %ld\n", block);
  109. X        /* NOTREACHED */
  110. X        }
  111. X    if (fread (ind_blk, sizeof (daddr_t), num_blocks, fsys) != num_blocks){
  112. X        error (errno, "\nerror reading indirect block %ld\n", block);
  113. X        /* NOTREACHED */
  114. X        }
  115. X    pos = block;
  116. X
  117. X    /*
  118. X     * scan the data blocks looking for numbers out of sequence
  119. X     */
  120. X    sparse = FALSE;
  121. X    for (i = 0; i < num_blocks; i++){
  122. X        new_pos = ind_blk [i];
  123. X        if (new_pos == 0){
  124. X            sparse = TRUE;
  125. X            continue;
  126. X            }
  127. X        if (sparse){
  128. X            data->sparse++;
  129. X            }
  130. X        data->data_blocks += (blk_size (fil_sys, inode, lbn+i) / fsize(fil_sys));
  131. X        data->total_blocks+= (blk_size (fil_sys, inode, lbn+i) / fsize(fil_sys));
  132. X        test_fragmentation (new_pos, pos, data);
  133. X        pos = new_pos;
  134. X        }
  135. X    return pos;
  136. X    }
  137. X
  138. X/*
  139. X * chk_double_indirects : scans a block containing a list of indirect
  140. X * blocks, checking for data block numbers that are out of sequence.
  141. X */
  142. Xdaddr_t chk_double_indirects (block, cur_pos, data, inode, lbn)
  143. Xdaddr_t block;                            /* indirect block to check */
  144. Xdaddr_t cur_pos;                          /* current block offset */
  145. Xstruct file_data *data;                   /* current file statistics */
  146. Xstruct dinode *inode;                     /* inode being processed */
  147. Xdaddr_t lbn;                              /* logical blk_no of 1st data block */
  148. X{
  149. X    daddr_t dindirect_blk[MAXINDIR];      /* holds a double-indirect
  150. X                                           * block */
  151. X    int i;                                /* loop counter */
  152. X    int num_blocks;                       /* number of indirect blocks
  153. X                                           * in a d-i block */
  154. X    boolean sparse;                       /* potential sparse file
  155. X                                           * detected */
  156. X
  157. X    num_blocks = nindir(fil_sys);
  158. X    data->total_blocks += (bsize(fil_sys) / fsize(fil_sys));
  159. X
  160. X    /*
  161. X     * the double-indirect block itself should be in sequence with the
  162. X     * data blocks
  163. X     */
  164. X    test_fragmentation (block, cur_pos, data);
  165. X
  166. X    /*
  167. X     * get the d-i block
  168. X     */
  169. X    if (fseek (fsys, block * block_size, 0)){
  170. X        error (errno, "\nerror seeking double indirect block %ld\n",
  171. X             block);
  172. X        /* NOTREACHED */
  173. X        }
  174. X    if (fread (dindirect_blk, sizeof (daddr_t), num_blocks, fsys) != num_blocks){
  175. X        error (errno, "\nerror reading double indirect block %ld\n",
  176. X             block);
  177. X        /* NOTREACHED */
  178. X        }
  179. X
  180. X    /*
  181. X     * scan through the d-i block
  182. X     */
  183. X    cur_pos = block;
  184. X    sparse = FALSE;
  185. X    for (i = 0; i < num_blocks; i++){
  186. X        if (dindirect_blk[i] == 0){
  187. X            sparse = TRUE;
  188. X            continue;
  189. X            }
  190. X        if (sparse){
  191. X            data->sparse++;
  192. X            }
  193. X        cur_pos = chk_indirects (dindirect_blk[i],
  194. X                     cur_pos,
  195. X                     data,
  196. X             inode,
  197. X                     lbn + (i * nindir(fil_sys)));
  198. X        }
  199. X    return cur_pos;
  200. X    }
  201. X
  202. X/*
  203. X * chk_triple_indirects : scans a block containing a list of double
  204. X * indirect blocks, looking for data block numbers that are out of sequence.
  205. X */
  206. Xdaddr_t chk_triple_indirects (block, cur_pos, data, inode, lbn)
  207. Xdaddr_t block;                            /* indirect block to check */
  208. Xdaddr_t cur_pos;                          /* current block offset */
  209. Xstruct file_data *data;                   /* current file statistics */
  210. Xstruct dinode *inode;                     /* inode being processed */
  211. Xdaddr_t lbn;                              /* log. blk_no of 1st data block */
  212. X{
  213. X    daddr_t tindirect_blk[MAXINDIR];      /* holds a triple-indirect
  214. X                                           * block */
  215. X    int i;                                /* loop counter */
  216. X    int num_blocks;                       /* number of double-indirect
  217. X                                           * blocks in a triple-i blk */
  218. X    boolean sparse;                       /* potential sparse file
  219. X                                           * detected */
  220. X
  221. X
  222. X    num_blocks = nindir(fil_sys);
  223. X    data->total_blocks += (bsize(fil_sys) / fsize(fil_sys));
  224. X
  225. X    /*
  226. X     * the triple-indirect block itself should be in sequence with the
  227. X     * data blocks
  228. X     */
  229. X    test_fragmentation (block, cur_pos, data);
  230. X
  231. X    /*
  232. X     * get the t-i block
  233. X     */
  234. X    if (fseek (fsys, block * block_size, 0)){
  235. X        error (errno, "\nerror seeking triple indirect block %ld\n",
  236. X             block);
  237. X        /* NOTREACHED */
  238. X        }
  239. X    if (fread (tindirect_blk, sizeof (daddr_t), num_blocks, fsys) != num_blocks){
  240. X        error (errno, "\nerror reading triple indirect block %ld\n",
  241. X             block);
  242. X        /* NOTREACHED */
  243. X        }
  244. X
  245. X    /*
  246. X     * scan through the t-i block
  247. X     */
  248. X    cur_pos = block;
  249. X    sparse = FALSE;
  250. X    for (i = 0; i < num_blocks; i++){
  251. X        if (tindirect_blk[i] == 0){
  252. X            sparse = TRUE;
  253. X            continue;
  254. X            }
  255. X        if (sparse){
  256. X            data->sparse++;
  257. X            }
  258. X        cur_pos = chk_double_indirects (tindirect_blk[i],
  259. X                        cur_pos,
  260. X                        data,
  261. X            inode,
  262. X                        lbn + (i * nindir (fil_sys) * nindir (fil_sys)));
  263. X        }
  264. X    return cur_pos;
  265. X    }
  266. X
  267. X/*
  268. X * chk_file : scans the data block numbers of an i-node, looking for
  269. X * block numbers that are out of sequence, and would thus result in excess
  270. X * track-to-track seeking.  This function also checks directory files for
  271. X * indirection, and performs a simple consistency check on all file sizes.
  272. X */
  273. Xvoid chk_file (inode, inode_number, data)
  274. Xstruct dinode *inode;                  /* inode info structure */
  275. Xint inode_number;                      /* inode number to be
  276. X                                        * checked */
  277. Xstruct file_data *data;                /* current file statistics */
  278. X{
  279. X    daddr_t pos;                       /* current block */
  280. X    daddr_t new_pos;                   /* next block in file */
  281. X    int i;                             /* loop counter */
  282. X    long file_size;                    /* file size computed by
  283. X                                        * actual byte count */
  284. X    boolean sparse;                    /* potential sparse file
  285. X                                        * detected */
  286. X
  287. X    pos = blk_no (dta_blk (inode, 0)); /* first data block */
  288. X
  289. X    /*
  290. X     * do some simple-minded statistics gathering
  291. X     */
  292. X    if (inode->di_nlink > 1){          /* multi-linked files */
  293. X        linked_files++;
  294. X        }
  295. X
  296. X    if (FILE_TYPE (inode) == S_IFDIR){ /* got a directory */
  297. X        num_directories++;
  298. X        }
  299. X
  300. X    /*
  301. X     * no fragmentation checks for special files or 0-length files
  302. X     */
  303. X    if (IS_SPECIAL (inode->di_mode)){
  304. X        num_specials++;
  305. X    if (debug)printf ("inode %d is special\n", inode_number);
  306. X        return;
  307. X        }
  308. X
  309. X    if (inode->di_size == 0){
  310. X    if (debug)printf ("inode %d is empty\n", inode_number);
  311. X        return;                        /* ignore 0-size files */
  312. X        }
  313. X
  314. X    data->data_blocks = data->total_blocks = (blk_size(fil_sys, inode, 1) / fsize (fil_sys));
  315. X    if (debug)printf ("blk_size returns %ld\n", blk_size (fil_sys, inode, 1));
  316. X
  317. X    /*
  318. X     * scan the data blocks looking for numbers out of sequence
  319. X     */
  320. X    sparse = FALSE;
  321. X    for (i = 1; i < NDADDR; i++){
  322. X        new_pos = blk_no (dta_blk (inode, i));
  323. X        if (new_pos == 0){             /* end of file */
  324. X            sparse = TRUE;
  325. X            continue;
  326. X            }
  327. X        if (sparse){
  328. X            data->sparse++;
  329. X            }
  330. X        data->data_blocks += (blk_size (fil_sys, inode, i) / fsize (fil_sys));
  331. X        data->total_blocks += (blk_size (fil_sys, inode, i) / fsize (fil_sys));
  332. X    if (debug)printf ("  blk_size returns %ld\n", blk_size(fil_sys,inode,i));
  333. X        test_fragmentation (new_pos, pos, data);
  334. X        pos = new_pos;
  335. X        }
  336. X
  337. X    /*
  338. X     * Indirect block 0, if non-zero, is the number of the block
  339. X     * which contains the next NINDIR data block numbers.  It should
  340. X     * also be in sequence with the data blocks.
  341. X     */
  342. X    if (blk_no (indir_blk (inode, 0))){
  343. X        indirects++;
  344. X        /*
  345. X         * if a directory contains indirection, it is too large for
  346. X         * efficient access.  Report it.
  347. X         */
  348. X        if (FILE_TYPE (inode) == S_IFDIR){
  349. X            printf ("inode %d is a large directory\n", inode_number);
  350. X            big_directories++;
  351. X            }
  352. X        pos = chk_indirects (blk_no (indir_blk (inode, 0)),
  353. X                     pos,
  354. X                     data,
  355. X             inode,
  356. X                     NDADDR);
  357. X        }
  358. X
  359. X    /*
  360. X     * Indirect block 1, if non-zero, is the number of the block which contains
  361. X     * the next NINDIR INDIRECT block numbers.  It should also be
  362. X     * in sequence with the data blocks.  This block is called a "double-
  363. X     * indirect" block.
  364. X     */
  365. X    if (blk_no (indir_blk (inode, 1))){
  366. X        double_indirects++;
  367. X        if (rpt_indirects){
  368. X            printf ("double indirection : %d\n", inode_number);
  369. X            }
  370. X        pos = chk_double_indirects (blk_no (indir_blk (inode, 1)),
  371. X                        pos,
  372. X                        data,
  373. X            inode,
  374. X                        NDADDR+nindir(fil_sys));
  375. X        }
  376. X
  377. X    /*
  378. X     * Indirect block 2, if non-zero, is the number of the block which contains
  379. X     * the next NINDIR DOUBLE-INDIRECT block numbers.  It should
  380. X     * also be in sequence with the data blocks.  This block is called a
  381. X     * "triple-indirect" block.
  382. X     */
  383. X    if (blk_no (indir_blk (inode, 2))){
  384. X        triple_indirects++;
  385. X        if (rpt_indirects){
  386. X            printf ("triple indirection : %d\n", inode_number);
  387. X            }
  388. X        pos = chk_triple_indirects (blk_no (indir_blk (inode, 2)),
  389. X                        pos,
  390. X                        data,
  391. X            inode,
  392. X                        NDADDR + (nindir (fil_sys) * nindir (fil_sys)));
  393. X        }
  394. X
  395. X    /*
  396. X     * detect and display sparse files
  397. X     */
  398. X    if (data->sparse){
  399. X        printf ("inode %d is sparse\n", inode_number);
  400. X        sparse_files++;
  401. X        }
  402. X
  403. X    /*
  404. X     * do a simple check to detect possible file-size errors (a la
  405. X     * fsck phase 1)
  406. X     */
  407. X    file_size = (inode->di_size + (block_size - 1)) / block_size;
  408. X    data->wasted = (block_size - (inode->di_size % block_size));
  409. X    if (file_size != data->data_blocks){
  410. X        size_errors++;
  411. X        if (rpt_errors){
  412. X            printf ("inode %d, inconsistent file size : actual blocks = %ld, computed = %ld (%ld bytes)\n",
  413. X                inode_number, data->data_blocks, 
  414. X                file_size, inode->di_size);
  415. X            }
  416. X        }
  417. X    }
  418. X
  419. X/*
  420. X * scan : scan through each i-node of a file system, compiling statistics
  421. X * regarding fragmentation and indirection.
  422. X */
  423. Xvoid scan (){
  424. X    int    i, j;                        /* loop counters */
  425. X    struct dinode i_node[MAXINOPB];     /* holds a block of inodes */
  426. X    struct file_data data;              /* per-inode statistics */
  427. X
  428. X    for (i = first_inode; i < num_inodes(fil_sys); i+=inopb(fil_sys)){
  429. X
  430. X        /*
  431. X         * for efficiency, read a block of i-nodes at a time
  432. X         */
  433. X        get_inodes (i, i_node, inopb(fil_sys));
  434. X
  435. X        /*
  436. X         * scan through each i-node that was read in
  437. X         */
  438. X        for (j = 0; i+j <= num_inodes(fil_sys) && j < inopb(fil_sys); j++){
  439. X            if (debug){
  440. X                printf ("inode %d = mode %o\r", i+j, i_node[j].di_mode);
  441. X                }
  442. X            if (i+j <= 1)continue;                 /* don't scan i-node 1 */
  443. X            if (i_node[j].di_mode != 0){           /* unused i-node ? */
  444. X                init_stats (&data, i+j, i_node[j].di_size);
  445. X                chk_file (&i_node[j], i+j, &data); /* scan blocks in file */
  446. X                log_stats (&data);
  447. X                }
  448. X            else {
  449. X                free_inodes++;
  450. X                }
  451. X            }
  452. X        }
  453. X    }
  454. X
  455. X/*
  456. X * anal_file : analyzes a single file for fragmentation.
  457. X */
  458. Xvoid anal_file (ino, fname)
  459. Xint ino;                        /* i-node number */
  460. Xchar *fname;                    /* filename of this inode */
  461. X{
  462. X    struct file_data data;      /* current file statistics */
  463. X
  464. X    struct dinode i_node;       /* current inode data */
  465. X
  466. X    get_inodes (ino, &i_node, 1);
  467. X    init_stats(&data, ino, i_node.di_size);
  468. X    chk_file (&i_node, ino, &data);
  469. X    log_stats (&data);
  470. X    printf ("   %-14s\t%6d    %6ld   %6ld   %6.2f%%  %6.1f  %ld\n",
  471. X        fname, data.inode, data.seeks+1, 
  472. X        data.total_blocks, data.fragm*100,
  473. X        data.rel_cost, data.wasted);
  474. X    }
  475. END_OF_chkfile.c
  476. if test 15316 -ne `wc -c <chkfile.c`; then
  477.     echo shar: \"chkfile.c\" unpacked with wrong size!
  478. fi
  479. # end of overwriting check
  480. fi
  481. if test -f fsconfig.h -a "${1}" != "-c" ; then 
  482.   echo shar: Will not over-write existing file \"fsconfig.h\"
  483. else
  484. echo shar: Extracting \"fsconfig.h\" \(12938 characters\)
  485. sed "s/^X//" >fsconfig.h <<'END_OF_fsconfig.h'
  486. X/* @(#)$Id: fsconfig.h, V4.1.1.1 88/11/18 17:38:35 $ */
  487. X
  488. X/*
  489. X * fsconfig.h - fsanalyze configuration-specific definitions
  490. X * Version  : 4.1.1.1 - 88/11/18 17:38:35
  491. X *
  492. X * Author   : Michael J. Young
  493. X * USmail   : Software Development Technologies, Inc.
  494. X *            375 Dutton Rd
  495. X *            Sudbury MA 01776
  496. X * UUCP     : harvard!sdti!mjy
  497. X * Internet : mjy@sdti.SDTI.COM
  498. X *
  499. X * =========================================================================
  500. X * Note : This program has been placed in the public domain to permit
  501. X * unrestricted distribution and use.  I have placed no copyright on it, but
  502. X * I request that you keep me informed about any enhancements and bug fixes
  503. X * you make so I can keep an up-to-date copy for further distribution.
  504. X * =========================================================================
  505. X */
  506. X
  507. X/*
  508. X * Modification History:
  509. X *
  510. X *    Date       Author                   Description
  511. X * -----------  --------  -----------------------------------------------
  512. X * Wed Mar  9 17:51:38 EST 1988 - M. Young (mjy@sdti.SDTI.COM)
  513. X *    Originated.
  514. X *
  515. X * Wed Apr 13 17:18:06 EDT 1988 - M. Young (mjy@sdti.SDTI.COM)
  516. X *    Completed port to BSD.  Added fsize(), first_inode, and Sec_per_blk
  517. X *    macros.
  518. X *
  519. X * Wed Jun 15 14:06:35 EDT 1988 - M. Young (mjy@sdti.SDTI.COM)
  520. X *    Added NUMOFFEND macro.
  521. X *
  522. X * Tue Jul 26 15:27:52 EDT 1988 - M. Young (mjy@sdti.SDTI.COM)
  523. X *    Modified Opt_interleave and cyl_pos macros to more closely reflect BSD
  524. X *    placement algorithm (still unsure of this!).
  525. X *
  526. X * Thu Jul 28 16:43:20 EDT 1988 - M. Young (mjy@sdti.SDTI.COM)
  527. X *    Opt_interleave formula now makes sense.
  528. X *
  529. X * Mon Aug 08 11:27:39 EDT 1988 - M. Young (mjy@sdti.SDTI.COM),
  530. X *    Revised OS_TYPE and FS_TYPE macros to avoid name-space conflicts
  531. X *
  532. X * Wed Nov 16 11:31:32 EST 1988 - M. Young (mjy@sdti.SDTI.COM),
  533. X *    Placed under SCCS
  534. X *
  535. X * Fri Nov 18 17:37:08 EST 1988 - M. Young (mjy@sdti.SDTI.COM),
  536. X *    Removed #defines for SUPERBOFF for all but XENIX/286
  537. X */
  538. X
  539. X/*
  540. X * One of the things fsanalyze displays is a list of the most fragmented
  541. X * files.  The macro NUMOFFEND determines how many of those files to report.
  542. X * The report is in double column format, so the number should be divisible
  543. X * by 2.  Ideally, this number should be set so that the report fits on
  544. X * a single screen.  For a 24-line display, the suggested number is 10
  545. X * (5 lines).
  546. X */
  547. X#ifndef NUMOFFEND
  548. X# define NUMOFFEND    10    /* number of top offenders to report    */
  549. X#endif
  550. X
  551. X/*
  552. X * File System types - define _FS_TYPE accordingly
  553. X */
  554. X#define FS_ATT         1       /* AT&T File system derivatives, incl Version 7,
  555. X                                * System III, & System V (sVr2 & sVr3) */
  556. X#define FS_BSD         2       /* BSD fast file system derivatives */
  557. X#define FS_BSD_NFS     3       /* BSD fast file system with NFS support */
  558. X
  559. X/*
  560. X * OS-types -- although the basic structure of the file system remains
  561. X * constant, many ports of Unix contain minor modifications.  Eventually,
  562. X * the following should contain a complete list of special cases.  Those
  563. X * OS's which do not contain special cases should be referred to as OS_ATT
  564. X * or OS_BSD.
  565. X */
  566. X#define OS_ATT         1       /* Generic AT&T OS, no special cases */
  567. X#define OS_BSD         2       /* Generic BSD 4.2 or later FFS, no special
  568. X                                * cases */
  569. X#define OS_XENIX_286   4       /* XENIX/286 */
  570. X#define OS_UPORT_286   5       /* Microport System V/AT */
  571. X
  572. X#ifndef FS_TYPE
  573. X# define FS_TYPE    FS_ATT
  574. X#endif
  575. X
  576. X#ifndef OS_TYPE
  577. X# define OS_TYPE    OS_ATT
  578. X#endif
  579. X
  580. X
  581. X/***************************************************************************
  582. X *                            file system macros                           *
  583. X ***************************************************************************/
  584. X
  585. X/*
  586. X * File systems based on Version 7 Unix (System III and System V) are
  587. X * significantly different than those based on the BSD Fast File System.
  588. X * The following macros are defined to facilitate portable access to the
  589. X * superblock and inode information.  Where possible, macro names 
  590. X * the BSD <sys/fs.h> are used, and these macros must be created for non
  591. X * BSD file systems.
  592. X *
  593. X *    SUPERBOFF                 Byte offset of the superblock
  594. X *    DEV_BSIZE                 Physical device block size (sector size)
  595. X *    MAXBSIZE                  Maximum block size of any file system
  596. X *    MAXINOPB                  Maximum number of inodes per block (based
  597. X *                              on largest possible block size of any file
  598. X *                              system
  599. X *    MAXINDIR                  Maximum number of indirect blocks per block
  600. X *                              (based on largest possible block size of any
  601. X *                              file system)
  602. X *    inopb(fs)                 Number of inodes per block of a given file
  603. X *                              system
  604. X *    nindir(fs)                Number of indirect blocks per block in a
  605. X *                              given file system
  606. X *    bsize(fs)                 Block size (in bytes) of a given file system
  607. X *    fsize(fs)                 Fragment size (in bytes) -- same as bsize()
  608. X *                              in non-BSD file systems
  609. X *    fssize(fs)                Total size of a file system (in blocks of
  610. X *                              bsize(fs) bytes)
  611. X *    dsize(fs)                 Number of data blocks in the file system
  612. X *    isize(fs)                 Total number of blocks reserved for inode info
  613. X *    num_inodes(fs)            Number of inodes supported by the file system
  614. X *    first_inode               number of first inode in file system
  615. X *    iblkno(fs)                Block number of the first inode in a file
  616. X *                              system (or cylinder group)
  617. X *    sec_per_cyl(fs)           Number of physical sectors per cylinder in
  618. X *                              a given file system
  619. X *    is_ok(fs)                 TRUE if the file system is not in need of
  620. X *                              checking (with fsck(1M))
  621. X *    opt_interleave(fs)        The optimum sector interleave which will result
  622. X *                              in minimum rotational delay.
  623. X *    Sec_per_blk               Number of sectors per logical block
  624. X *    freespace(fs,res)         Total number of free blocks in a file system,
  625. X *                              given a percentage that must be held in reserve
  626. X *    inode_block(fs,inode)     Computes block number which contains inode info
  627. X *    inode_offset(fs,inode)    Computes offset of an inode within its block
  628. X *    blk_size(fs,inode,lbn)    Computes the size of a data block in bytes
  629. X *    cylinder(fs,blk)          Computes cylinder which contains specified
  630. X *                              block
  631. X *    cyl_pos(fs,blk)           Computes relative sector position of the
  632. X *                              specified block in its cylinder.
  633. X *    NDADDR                    Number of direct data blocks within inode
  634. X *    NIADDR                    Number of indirect data blocks within inode
  635. X *    dta_blk(blk)              Returns pointer to data block within inode
  636. X *                              cast as (char *) for compatibility with
  637. X *                              AT&T file systems.
  638. X *    indir_blk(blk)            Returns pointer to indirect block within inode
  639. X *                              cast as (char *) for compatibility with
  640. X *                              AT&T file systems.
  641. X */
  642. X
  643. X/*
  644. X * Sec_per_blk : Number of physical sectors (size DEV_BSIZE) per logical block.
  645. X */
  646. X#define Sec_per_blk             (block_size / DEV_BSIZE)
  647. X
  648. X#if (FS_TYPE == FS_ATT)
  649. X
  650. X/*
  651. X * The following definitions provide the above-listed macros for a
  652. X * "conventional" Unix file system.  Any versions of Unix that use a
  653. X * file system structure that was derived directly from Version 7 Unix
  654. X * (e.g., System III, System V, XENIX) use these definitions.
  655. X */
  656. X
  657. Xtypedef struct filsys superblk_t;       /* superblock structure definition */
  658. X
  659. X/* SCO XENIX doesn't have SUPERBOFF, so we must set it explicitly.  Note
  660. X * that XENIX/286 seems to want the value BSIZE*SUPERB (==1024L), yet
  661. X * XENIX/386 is "normal" SystemV (512L).
  662. X */
  663. X# if (OS_TYPE == OS_XENIX_286)
  664. X#   define SUPERBOFF    (BSIZE*SUPERB)
  665. X# endif
  666. X
  667. X# define DEV_BSIZE      512
  668. X
  669. X/*
  670. X * MAXBSIZE is defined as the largest possible BSIZE for any file system.
  671. X * The largest I have come across in System V ports is 2048.  If a larger
  672. X * one is encountered, MAXBSIZE should be increased accordingly.
  673. X */
  674. X# define MAXBSIZE       2048
  675. X# define MAXINOPB       (MAXBSIZE / sizeof (struct dinode))
  676. X# define MAXINDIR       (MAXBSIZE / sizeof (daddr_t))
  677. X# ifdef FsINOPB
  678. X#  define inopb(fs)    FsINOPB(fs)
  679. X# else
  680. X#  define inopb(fs)     INOPB
  681. X# endif
  682. X# ifdef FsNINDIR
  683. X#  define nindir(fs)    FsNINDIR(fs)
  684. X# else
  685. X#  define nindir(fs)    NINDIR
  686. X# endif
  687. X
  688. X/*
  689. X * The following definition is used to determine the logical block size for
  690. X * a particular file system.  Normally, SBUFSIZE == BSIZE == the logical
  691. X * block size.  However, in systems that have dual file system support
  692. X * enabled (rare), BSIZE is usually set to the block size of the smaller
  693. X * file system, whereas SBUFSIZE is set to the larger.  If this is
  694. X * different in your system, change the following macro accordingly.
  695. X */
  696. X# ifdef Fs2b
  697. X#  define bsize(fs)      ((fs)->s_type == Fs2b ? SBUFSIZE : BSIZE)
  698. X# else
  699. X#  define bsize(fs)     (BSIZE)
  700. X# endif
  701. X# define fsize(fs)       (bsize(fs))
  702. X
  703. X# define fssize(fs)      ((fs)->s_fsize)
  704. X# define dsize(fs)       ((fs)->s_fsize - (fs)->s_isize)
  705. X# define isize(fs)       ((fs)->s_isize)
  706. X# define num_inodes(fs)  (((fs)->s_isize-ROOTINO) * inopb(fs))
  707. X# define first_inode     1
  708. X# define iblkno(fs)      2
  709. X# define sec_per_cyl(fs) ((fs)->s_dinfo[1])
  710. X
  711. X/*
  712. X * Note that the standard check for file system integrity does not work
  713. X * on Microport systems because a clean, unmounted file system is not set
  714. X * to FsOKAY, but some other undocumented constant.  It is therefore
  715. X * strongly recommended that the HAVE_FSSTAT macro be defined for Microport
  716. X * systems.
  717. X */
  718. X# if (OS_TYPE == OS_UPORT_286)
  719. X#  define is_ok(fs) (TRUE)
  720. X#  ifndef HAVE_FSSTAT
  721. X#   define HAVE_FSSTAT
  722. X#  endif
  723. X# else
  724. X#  if (OS_TYPE == OS_XENIX_286)
  725. X#   define is_ok(fs) (TRUE)
  726. X#  else
  727. X#   define is_ok(fs) ((fs)->s_state == FsOKAY) || ((fs)->s_state == FsACTIVE)
  728. X#  endif
  729. X# endif
  730. X
  731. X# define opt_interleave(fs)      ((fs)->s_dinfo[0])
  732. X# define freespace(fs,reserved)  ((fs)->s_tfree)
  733. X# define inode_block(fs,inode)   (iblkno(fs) + (((inode)-1) / inopb(fs)))
  734. X# define inode_offset(fs,inode)  (((inode)-1) % inopb(fs))
  735. X# define blk_size(fs, inode, lbn) (bsize(fs))
  736. X# define cylinder(fs,blk)        ((daddr_t)(blk) * Sec_per_blk / cyl_size)
  737. X# define cyl_pos(fs,blk)         ((daddr_t)(blk) * Sec_per_blk % cyl_size)
  738. X
  739. X/*
  740. X * inode data/indirect block access
  741. X */
  742. X# define NDADDR                  10    /* direct addresses in inode */
  743. X# define NIADDR                  3     /* indirect addresses in inode */
  744. X
  745. X# define dta_blk(ino, blk)       (&(ino)->di_addr[(blk)*3])
  746. X# define indir_blk(ino, blk)     (&(ino)->di_addr[((blk)+10)*3])
  747. X
  748. X#endif /* FS_TYPE == FS_ATT */
  749. X
  750. X#if ((FS_TYPE == FS_BSD) || (FS_TYPE == FS_BSD_NFS))
  751. X
  752. X/*
  753. X * The following definitions provide the above-listed macros for a derivative
  754. X * of the BSD Fast File System.
  755. X */
  756. X
  757. Xtypedef struct fs superblk_t;    /* superblock structure definition */
  758. X
  759. X# define SUPERBOFF        (SBLOCK * DEV_BSIZE)
  760. X/* DEV_BSIZE is defined in <sys/fs.h> */
  761. X/* MAXBSIZE is defined in <sys/fs.h>  */
  762. X# define MAXINOPB         (MAXBSIZE / sizeof (struct dinode))
  763. X# define MAXINDIR         (MAXBSIZE / sizeof (daddr_t))
  764. X# define inopb(fs)        INOPB(fs)
  765. X# define nindir(fs)       NINDIR(fs)
  766. X# define bsize(fs)        ((fs)->fs_bsize)
  767. X# define fsize(fs)        (bsize(fs) / (fs)->fs_frag)
  768. X# define fssize(fs)       ((fs)->fs_size)
  769. X# define dsize(fs)        ((fs)->fs_dsize)
  770. X# define isize(fs)        ((fs)->fs_ncg * (fs)->fs_ipg / inopb(fs))
  771. X# define num_inodes(fs)   (isize(fs) * inopb(fs))
  772. X# define first_inode      0
  773. X# define iblkno(fs)       ((fs)->fs_iblkno)
  774. X# define sec_per_cyl(fs)  ((fs)->fs_spc)
  775. X
  776. X/*
  777. X * How do we determine file system integrity on a BSD file system?
  778. X */
  779. X# define is_ok(fs)        (TRUE)
  780. X
  781. X# define opt_interleave(fs) \
  782. X         (((fs)->fs_rps * (fs)->fs_nsect * (fs)->fs_rotdelay /* sectors */\
  783. X           + ((NSPB(fs)*1000)-1)) / 1000)      /* round up */
  784. X
  785. X/* freespace(fs,res) is defined in <sys/fs.h> */
  786. X# define inode_block(fs,inode)   itod((fs),(inode))
  787. X# define inode_offset(fs,inode)  itoo((fs),(inode))
  788. X# define cylinder(fs,blk)        cbtocylno((fs),(blk))
  789. X# define cyl_pos(fs,blk)         (cbtorpos((fs),(blk)) * NRPOS)
  790. X
  791. X# define blk_size(fs, inode, lbn)  (dblksize (fs, inode, lbn))
  792. X
  793. X/*
  794. X * inode data/indirect block access
  795. X */
  796. X/* NDADDR is defined in inode.h */
  797. X/* NIADDR is defined in inode.h */
  798. X# define dta_blk(ino,blk)        ((char *)&((ino)->di_db[blk]))
  799. X# define indir_blk(ino,blk)      ((char *)&((ino)->di_ib[blk]))
  800. X
  801. X# endif  /* FS_TYPE == FS_BSD || FS_TYPE == FS_BSD_NFS */
  802. END_OF_fsconfig.h
  803. if test 12938 -ne `wc -c <fsconfig.h`; then
  804.     echo shar: \"fsconfig.h\" unpacked with wrong size!
  805. fi
  806. # end of overwriting check
  807. fi
  808. echo shar: End of archive 3 \(of 3\).
  809. cp /dev/null ark3isdone
  810. MISSING=""
  811. for I in 1 2 3 ; do
  812.     if test ! -f ark${I}isdone ; then
  813.     MISSING="${MISSING} ${I}"
  814.     fi
  815. done
  816. if test "${MISSING}" = "" ; then
  817.     echo You have unpacked all 3 archives.
  818.     rm -f ark[1-9]isdone
  819. else
  820.     echo You still need to unpack the following archives:
  821.     echo "        " ${MISSING}
  822. fi
  823. ##  End of shell archive.
  824. exit 0
  825. -- 
  826. Mike Young
  827. Software Development Technologies, Inc., Sudbury MA       Tel: +1 508 443 5779
  828. Internet: mjy@sdti.sdti.com                 UUCP: {harvard,mit-eddie}!sdti!mjy
  829.